package com.cspm.common.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * String工具类；主要对 StringUtils 的一些方法进行重写,达到更方便的使用
 *
 * @author CHENQUAN
 */
public class StringUtil extends StringUtils {

    /**
     * 一次性判断多个或单个对象为空。
     *
     * @param objects 多对象
     * @return 只要有一个元素为Blank，则返回true
     */
    public static boolean isBlank(Object... objects) {
        Boolean result = false;
        for (Object object : objects) {
            if (null == object || "".equals(object.toString().trim())
                    || "null".equals(object.toString().trim())) {
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     * 生成指定为位数的随机字符串（小写）
     *
     * @param length 随机字符串长度
     * @return 随机字符串（小写）
     */
    private static String getRandom(int length) {
        StringBuffer val = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            // 输出字母还是数字
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            // 字符串
            if ("char".equalsIgnoreCase(charOrNum)) {
                // 取得大写字母还是小写字母
                int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val.append((char) (choice + random.nextInt(26)));
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                // 数字
                val.append(String.valueOf(random.nextInt(10)));
            }
        }
        return val.toString().toLowerCase();
    }

    /**
     * 一次性判断多个或单个对象不为空。
     *
     * @param objects
     * @return 只要有一个元素不为Blank，则返回true
     * @author CHENQUAN
     */
    public static boolean isNotBlank(Object... objects) {
        return !isBlank(objects);
    }

    /**
     * 一次性判断多个字符串是否为空
     *
     * @param objects
     * @return
     * @author CHENQUAN
     * @date 2016年9月8日
     */
    public static boolean isBlank(String... objects) {
        Object[] object = objects;
        return isBlank(object);
    }

    public static boolean isNotBlank(String... objects) {
        Object[] object = objects;
        return !isBlank(object);
    }

    public static boolean isBlank(String str) {
        Object object = str;
        return isBlank(object);
    }

    public static boolean isNotBlank(String str) {
        Object object = str;
        return !isBlank(object);
    }

    /**
     * 判断一个字符串在数组中存在几个
     *
     * @param baseStr
     * @param strings
     * @return
     */
    public static int indexOf(String baseStr, String[] strings) {

        if (null == baseStr || baseStr.length() == 0 || null == strings)
            return 0;

        int i = 0;
        for (String string : strings) {
            boolean result = baseStr.equals(string);
            i = result ? ++i : i;
        }
        return i;
    }

    /**
     * 判断一个字符串是否为JSONObject,是返回JSONObject,不是返回null
     *
     * @param args
     * @return
     */
    public static JSONObject isJSONObject(String args) {
        JSONObject result = null;
        if (isBlank(args)) {
            return result;
        }
        try {
            return JSONObject.parseObject(args.trim());
        } catch (Exception e) {
            return result;
        }
    }

    /**
     * 判断一个字符串是否为JSONArray,是返回JSONArray,不是返回null
     *
     * @param args
     * @return
     */
    public static JSONArray isJSONArray(Object args) {
        JSONArray result = new JSONArray();
        if (isBlank(args)) {
            return null;
        }
        if (args instanceof JSONArray) {

            JSONArray arr = (JSONArray) args;
            for (Object json : arr) {
                if (json != null && json instanceof JSONObject) {
                    result.add(json);
                    continue;
                } else {
                    result.add(JSONObject.toJSON(json));
                }
            }
            return result;
        } else {
            return null;
        }

    }

    public static String trimToEmpty(Object str) {
        return (isBlank(str) ? "" : str.toString().trim());
    }

    /**
     * 将 Strig 进行 BASE64 编码
     *
     * @param str [要编码的字符串]
     * @param bf  [true|false,true:去掉结尾补充的'=',false:不做处理]
     * @return
     */
    public static String getBASE64(String str, boolean... bf) {
        if (StringUtils.isBlank(str))
            return null;
        String base64 = null;
        try {
            base64 = new sun.misc.BASE64Encoder().encode(str.getBytes("utf-8"));
            // 去掉 '='
            if (isBlank(bf) && bf[0]) {
                base64 = base64.replaceAll("=", "");
            }
        } catch (UnsupportedEncodingException uee) {
            System.err.println(uee.getMessage());
        }
        return base64;
    }

    /**
     * 将 BASE64 编码的字符串 s 进行解码
     *
     * @param s
     * @return
     * @author CHENQUAN
     * @date 2016年9月8日
     */
    public static String getStrByBASE64(String s) {
        if (isBlank(s))
            return "";
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(s);
            return new String(b);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 把Map转换成get请求参数类型,如 {"name"=20,"age"=30} 转换后变成 name=20&age=30
     *
     * @param map
     * @return
     */
    public static String mapToGet(Map<? extends Object, ? extends Object> map) {
        StringBuffer result = new StringBuffer();
        if (map == null || map.size() == 0) {
            // 返回空
        } else {
            Set<? extends Object> keys = map.keySet();
            for (Object key : keys) {
                result.append(((String) key + "=" + (String) map.get(key) + "&"));
            }
        }
        return isBlank(result) ? result.toString() : result.substring(0,
                result.length() - 1);
    }

    /**
     * 把一串参数字符串,转换成Map 如"?a=3&b=4" 转换为Map{a=3,b=4}
     *
     * @param args 参数字符串
     * @return Map
     */
    public static Map<String, ? extends Object> getToMap(String args) {
        if (isBlank(args)) {
            return null;
        }
        args = args.trim();
        // 如果是?开头,把?去掉
        if (args.startsWith("?")) {
            args = args.substring(1, args.length());
        }
        String[] argsArray = args.split("&");

        Map<String, Object> result = new HashMap<String, Object>();
        for (String ag : argsArray) {
            if (!isBlank(ag) && ag.indexOf("=") > 0) {
                String[] keyValue = ag.split("=");
                // 如果value或者key值里包含 "="号,以第一个"="号为主 ,如 name=0=3
                // 转换后,{"name":"0=3"}, 如果不满足需求,请勿修改,自行解决.
                String key = keyValue[0];
                String value = "";
                StringBuffer buf = new StringBuffer();
                for (int i = 1; i < keyValue.length; i++) {
                    buf.append(keyValue[i] + "=");
                }
                value = buf.length() > 0 ? buf.substring(0, buf.length() - 1)
                        : buf.toString();
                result.put(key, value);

            }
        }

        return result;
    }

    /**
     * 转换成Unicode
     *
     * @param str
     * @return
     */
    public static String toUnicode(String str) {
        String as[] = new String[str.length()];
        String s1 = "";
        for (int i = 0; i < str.length(); i++) {
            int v = str.charAt(i);
            if (v >= 19968 && v <= 171941) {
                as[i] = Integer.toHexString(str.charAt(i) & 0xffff);
                s1 = s1 + "\\u" + as[i];
            } else {
                s1 = s1 + str.charAt(i);
            }
        }
        return s1;
    }

    /**
     * 合并数据
     *
     * @param v
     * @return
     */
    public static String merge(Object... v) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < v.length; i++) {
            sb.append(v[i]);
        }
        return sb.toString();
    }

    /**
     * 字符串转urlcode
     *
     * @param value
     * @return
     */
    public static String strToUrlcode(String value) {
        try {
            value = java.net.URLEncoder.encode(value, "utf-8");
            return value;
        } catch (UnsupportedEncodingException e) {
            LoggerUtil.error(StringUtils.class, "字符串转换为URLCode失败,value:"
                    + value, e);
            e.printStackTrace();
            return null;
        }
    }

    /**
     * urlcode转字符串
     *
     * @param value
     * @return
     */
    public static String urlcodeToStr(String value) {
        try {
            value = java.net.URLDecoder.decode(value, "utf-8");
            return value;
        } catch (UnsupportedEncodingException e) {
            LoggerUtil.error(StringUtils.class, "URLCode转换为字符串失败;value:"
                    + value, e);
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 判断字符串是否包含汉字
     *
     * @param txt
     * @return
     */
    public static Boolean containsCN(String txt) {
        if (isBlank(txt)) {
            return false;
        }
        for (int i = 0; i < txt.length(); i++) {

            String bb = txt.substring(i, i + 1);

            boolean cc = java.util.regex.Pattern.matches("[\u4E00-\u9FA5]", bb);
            if (cc)
                return cc;
        }
        return false;
    }

    /**
     * 去掉HTML代码
     *
     * @param news
     * @return
     */
    public static String removeHtml(String news) {
        String s = news.replaceAll("amp;", "").replaceAll("<", "<")
                .replaceAll(">", ">");

        Pattern pattern = Pattern.compile(
                "<(span)?\\sstyle.*?style>|(span)?\\sstyle=.*?>",
                Pattern.DOTALL);
        Matcher matcher = pattern.matcher(s);
        String str = matcher.replaceAll("");

        Pattern pattern2 = Pattern.compile("(<[^>]+>)", Pattern.DOTALL);
        Matcher matcher2 = pattern2.matcher(str);
        String strhttp = matcher2.replaceAll(" ");

        String regEx = "(((http|https|ftp)(\\s)*((\\:)|：))(\\s)*(//|//)(\\s)*)?"
                + "([\\sa-zA-Z0-9(\\.|．)(\\s)*\\-]+((\\:)|(:)[\\sa-zA-Z0-9(\\.|．)&%\\$\\-]+)*@(\\s)*)?"
                + "("
                + "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])"
                + "(\\.|．)(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)"
                + "(\\.|．)(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)"
                + "(\\.|．)(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])"
                + "|([\\sa-zA-Z0-9\\-]+(\\.|．)(\\s)*)*[\\sa-zA-Z0-9\\-]+(\\.|．)(\\s)*[\\sa-zA-Z]*"
                + ")"
                + "((\\s)*(\\:)|(：)(\\s)*[0-9]+)?"
                + "(/(\\s)*[^/][\\sa-zA-Z0-9\\.\\,\\?\\'\\\\/\\+&%\\$\\=~_\\-@]*)*";
        Pattern p1 = Pattern.compile(regEx, Pattern.DOTALL);
        Matcher matchhttp = p1.matcher(strhttp);
        String strnew = matchhttp.replaceAll("").replaceAll(
                "(if[\\s]*\\(|else|elseif[\\s]*\\().*?;", " ");

        Pattern patterncomma = Pattern.compile("(&[^;]+;)", Pattern.DOTALL);
        Matcher matchercomma = patterncomma.matcher(strnew);
        String strout = matchercomma.replaceAll(" ");
        String answer = strout.replaceAll("[\\pP‘’“”]", " ")
                .replaceAll("\r", " ").replaceAll("\n", " ")
                .replaceAll("\\s", " ").replaceAll("　", "");

        return answer;
    }

    /**
     * 把数组的空数据去掉
     *
     * @param array
     * @return
     */
    public static List<String> array2Empty(String[] array) {
        List<String> list = new ArrayList<String>();
        for (String string : array) {
            if (StringUtils.isNotBlank(string)) {
                list.add(string);
            }
        }
        return list;
    }

    /**
     * 把数组转换成set
     *
     * @param array
     * @return
     */
    public static Set<?> array2Set(Object[] array) {
        Set<Object> set = new TreeSet<Object>();
        for (Object id : array) {
            if (null != id) {
                set.add(id);
            }
        }
        return set;
    }

    /**
     * serializable toString
     *
     * @param serializable
     * @return
     */
    public static String toString(Serializable serializable) {
        if (null == serializable) {
            return null;
        }
        try {
            return (String) serializable;
        } catch (Exception e) {
            return serializable.toString();
        }
    }

    /**
     * 判断是否为手机号码格式
     *
     * @param mobiles 待验证的手机号码
     * @return 若是返回true，反之则返回false
     */
    public static boolean checkMobileNo(String mobiles) {
        if (null == mobiles || mobiles.length() < 11) {
            return false;
        }
        Pattern p = Pattern
                .compile("^((13[0-9])|(14[0-9])|(15[0-9])|(17[0-9])|(18[0-9]))\\d{8}$");
        // 或者 "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$" --有问题
        // 或者电话号码："1([\\d]{10})|((\\+[0-9]{2,4})?\\(?[0-9]+\\)?-?)?[0-9]{7,8}"
        Matcher m = p.matcher(mobiles);
        // System.out.println(m.matches() + "---");
        return m.matches();
    }

    /**
     * 判断是否为手机号码格式[重载]
     *
     * @param mobiles 待验证的手机号码
     * @return 若是返回true，反之则返回false
     */
    public static boolean checkMobileNo(Long mobiles) {
        return checkMobileNo(mobiles.toString());
    }

    /**
     * 验证是否为邮箱格式
     *
     * @param email 邮箱
     * @return 若是返回true，反之则返回false
     */
    public static boolean checkEmail(String email) {
        boolean flag = false;
        try {
            String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
            Pattern regex = Pattern.compile(check);
            Matcher matcher = regex.matcher(email);
            flag = matcher.matches();
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }

    /**
     * 判断对象是否存在数组中
     *
     * @param object  待判断的对象
     * @param objects 比对数组
     * @return 若是返回true，反之则返回false
     * @author CHENQUAN
     * @date 2016年9月23日
     */
    public static boolean checkInArrays(Object object, Object[] objects) {
        if (Arrays.binarySearch(objects, object) > 0)
            return true;
        else
            return false;
    }

    /**
     * 判断字符串是否是乱码
     *
     * @param strName 字符串
     * @return 是否是乱码
     * @author CHENQUAN
     * @date 2016年11月18日
     */
    public static boolean isMessyCode(String strName) {
        Pattern p = Pattern.compile("\\s*|t*|r*|n*");
        Matcher m = p.matcher(strName);
        String after = m.replaceAll("");
        String temp = after.replaceAll("\\p{P}", "");
        char[] ch = temp.trim().toCharArray();
        float chLength = ch.length;
        float count = 0;
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            if (!Character.isLetterOrDigit(c)) {
                if (!isChinese(c)) {
                    count = count + 1;
                }
            }
        }
        float result = count / chLength;
        if (result > 0.4) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 判断字符是否是中文
     *
     * @param c
     * @return
     * @author CHENQUAN
     * @date 2016年11月18日
     */
    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }

    /**
     * 将小数的百分数转换为整数的百分数
     *
     * @param numeric 数字
     * @return 数字乘100，并且四舍五入保留一位小数
     * @author CHENQUAN
     * @date 2017年2月20日
     */
    public static Double getPercentage(Double numeric) {
        if (numeric <= 1) {
            numeric = getScale(numeric * 100);
        }
        return numeric;
    }

    /**
     * 保留小数点后1数并四舍五入 Double
     *
     * @param numeric 数字
     * @return 返回保留小数点后1数并四舍五入后的数值
     * @author CHENQUAN
     * @date 2017年1月10日
     */
    public static Double getScale(Double numeric) {
        return getScale(1, numeric);
    }

    /**
     * 保留小数点后1数并四舍五入 Float
     *
     * @param numeric 数字
     * @return 返回保留小数点后1数并四舍五入后的数值
     * @author CHENQUAN
     * @date 2017年1月10日
     */
    public static Float getScale(Float numeric) {
        return getScale(1, numeric);
    }

    /**
     * 保留小数点指定位数并四舍五入
     *
     * @param newScale 保留位数
     * @param numeric  数字
     * @return 返回四舍五入后的数字
     * @author CHENQUAN
     * @date 2016年12月11日
     */
    public static Double getScale(int newScale, Double numeric) {
        if (numeric != null) {
            BigDecimal bd = new BigDecimal(numeric);
            numeric = bd.setScale(newScale, BigDecimal.ROUND_HALF_UP)
                    .doubleValue();
        }
        return numeric;
    }

    /**
     * 保留小数点指定位数并四舍五入
     *
     * @param newScale 保留位数
     * @param numeric  数字
     * @return 返回四舍五入后的数字
     * @author CHENQUAN
     * @date 2016年12月11日
     */
    public static Float getScale(int newScale, Float numeric) {
        if (numeric != null) {
            BigDecimal bd = new BigDecimal(numeric);
            numeric = bd.setScale(newScale, BigDecimal.ROUND_HALF_UP)
                    .floatValue();
        }
        return numeric;
    }

    /**
     * 使用 Map按key进行升序排序
     *
     * @param map
     * @return
     */
    public static Map<String, Object> sortStringMapByKey(Map<String, Object> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        Map<String, Object> sortMap = new TreeMap<String, Object>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 升序排序
                return o1.compareTo(o2);
            }
        });
        sortMap.putAll(map);
        return sortMap;
    }

    /**
     * 使用 Map按key进行升序排序
     *
     * @param map
     * @return
     */
    public static Map<Integer, Object> sortIntegerMapByKey(Map<Integer, Object> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        Map<Integer, Object> sortMap = new TreeMap<Integer, Object>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // 升序排序
                return o1.compareTo(o2);
            }
        });
        sortMap.putAll(map);
        return sortMap;
    }

    /**
     * @param regex 正则表达式字符串
     * @param str   要匹配的字符串
     * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
     * @author CHENQUAN
     * @date 2017年7月5日
     */
    public static boolean match(String regex, String str) {
        if (str == null || regex == null) {
            return false;
        }
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    public static void main(String[] args) {
        System.out.println(getRandom(10));
    }
}
